package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.PasswordConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.EmployeeDTO;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.dto.EmployeePageQueryDTO;
import com.sky.entity.Employee;
import com.sky.exception.AccountLockedException;
import com.sky.exception.AccountNotFoundException;
import com.sky.exception.PasswordErrorException;
import com.sky.mapper.EmployeeMapper;
import com.sky.result.PageResult;
import com.sky.service.EmployeeService;
import lombok.val;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */
    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();

        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);

        //2、处理各种异常情况（用户名不存在、密码不对、账号被锁定）
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
        //对前端传过来的 明文密码进行加密处理
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!password.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //3、返回实体对象
        return employee;
    }

    /**
     * 新增员工
     * @param employeeDTO
     */
    @Override
    public void save(EmployeeDTO employeeDTO) {
        System.out.println("当前线程的 id" +Thread.currentThread().getId()); // 获取 ID
        Employee employee = new Employee(); // 先来创建一个 员工实体

        // 然后初始化员工数据
       // employee.setName(employeeDTO.getName());

        // 这里可以使用 对象属性拷贝 来之间传入
        BeanUtils.copyProperties(employeeDTO,employee); // 这里是将 DTO 里面的属性 拷贝到 实体对象 employee 当中
        // 因为这两个有相同的属性
        // 这里面只是把 DTO 和 实体类里面的相同的属性给拷贝进去了
        // 剩余的属性还要自己创建

        // 设置账号的状态， 默认是正常的状态 1 表示正常     0 表示锁定
        employee.setStatus(StatusConstant.ENABLE); // 这里面我们定义了常量类 防止硬编码，

        // 设置密码， 新增的一般都使用 默认密码 123456
       // employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes())); // 而这里面不是直接存 123456，
        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
        // 因为这个数据是要保存到数据库中的， 所以要 进行 MD5 加密
        // 定义了一个 PasswordConstant.DEFAULT_PASSWORD 常量

      /*  // 设置当前记录的创建时间  和 修改时间
        // 使用当前的系统时间就可以了

        employee.setCreateTime(LocalDateTime.now());
        employee.setUpdateTime(LocalDateTime.now());

        // 设置当前记录创建人 id 和 修改人 id
        //
        employee.setCreateUser(BaseContext.getCurrentId());
        employee.setUpdateUser(BaseContext.getCurrentId());*/
        // 这里面已经对上述的赋值操作 有一个 公共的赋值了
        // 所以这一部分也就不再需要了

        // 接下来操作数据
        employeeMapper.insert(employee);
    }

    /**
     * 分页查询
     *
     * @param employeePageQueryDTO
     * @return
     */
     public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO){
        //最底层是基于数据库层的分页
         // select * from employee limit 0, 10
         // 这样写的话 还需要自己进行计算把页数计算出来
         // 一般都是很麻烦的， 所以这里用到一个插件
         // pagehelper
         // 要想使用这个插件 需要 在 pom 文件中 引入这个依赖
         // 引入进来之后 就可以这样写了

         // 开始分页查询
         PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
         // 传入之前已经写好的页码 和 记录 数

         // 接下来编写 sql 来完成查询
         Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO); // 因为DTO里面含有我们的查询条件， name ，
         // 这个name 需要我们动态的拼接到sql中去
         // 这里的返回格式 是 pageHelper 固定的

         // 这个 pageQuery 和 startPage 有什么样的关系呢？ 它是怎么知道要实现分页查询呢？
         // startPage 里面 调用了 很多重载方法， 里卖弄最重要的方法是 setLocalPage

         long total = page.getTotal();
         List<Employee> records = page.getResult();
         return new PageResult(total,records);
     }

    /**
     * 启用禁用员工账号
     * @param status
     * @param id
     */
     public void startOrStop(Integer status, Long id){
        // update employee set status = ？ where id = ?

         // 创建实体的第一种写法
//         Employee employee = new Employee();
//         employee.setStatus(status);
//         employee.setId(id);

         // 创建实体对象的第二种写法，用 Builder
         Employee employee = Employee.builder()
                 .status(status)
                 .id(id)
                 .build();
         employeeMapper.update(employee);
     }

    /**
     * 根据 id 查询员工
     * @param id
     * @return
     */
     public Employee getById(Long id){
        Employee employee =  employeeMapper.getById(id);

        // 这里是要传递密码的
         // 这里面需要处理一下
         // 为了防止泄露, 加强安全性
         employee.setPassword("****");
        return employee;
     }

    /**
     * 编辑员工信息
     * @param employeeDTO
     */
   public void update(EmployeeDTO employeeDTO){
       // 需要对数据进行转换
       // 把 employeeDTO 改为 employee
       Employee employee = new Employee();
       BeanUtils.copyProperties(employeeDTO,employee);

//       employee.setUpdateTime(LocalDateTime.now());
//       employee.setUpdateUser(BaseContext.getCurrentId());

       // 这里面已经对上述的赋值操作 有一个 公共的赋值了
       // 所以这一部分也就不再需要了
       employeeMapper.update(employee);
   }
}
